import { RegisterComponent } from '@feng3d/ecs';
import { EventEmitter } from '@feng3d/event';
import { watcher } from '@feng3d/watcher';
import { Component3D, Node3DEventMap, PerspectiveCamera3D } from 'feng3d-three';
import { OrbitControls } from '../thirdparty/three/imports';

declare module '@feng3d/ecs'
{
    interface ComponentMap { OrbitControls3D: OrbitControls3D; }
}

export interface OrbitControls3DEventMap extends Node3DEventMap
{
    change: any;
}

/**
 * 包装`three`中`OrbitControls`。
 */
@RegisterComponent({ name: 'OrbitControls3D' })
export class OrbitControls3D extends Component3D
{
    _controls: OrbitControls;

    declare readonly emitter: EventEmitter<OrbitControls3DEventMap>;

    camera: PerspectiveCamera3D;

    domElement: HTMLCanvasElement;

    get target()
    {
        return this._controls.target;
    }

    get enablePan()
    {
        return this._controls.enablePan;
    }
    set enablePan(v)
    {
        this._controls.enablePan = v;
    }

    get enableZoom()
    {
        return this._controls.enableZoom;
    }
    set enableZoom(v)
    {
        this._controls.enableZoom = v;
    }

    get minDistance()
    {
        return this._controls.minDistance;
    }

    set minDistance(v)
    {
        this._controls.minDistance = v;
    }

    get maxDistance()
    {
        return this._controls.maxDistance;
    }

    set maxDistance(v)
    {
        this._controls.maxDistance = v;
    }

    get enableDamping()
    {
        return this._controls.enableDamping;
    }

    set enableDamping(v)
    {
        this._controls.enableDamping = v;
    }

    get maxPolarAngle()
    {
        return this._controls.maxPolarAngle;
    }

    set maxPolarAngle(v)
    {
        this._controls.maxPolarAngle = v;
    }

    get autoRotate()
    {
        return this._controls.autoRotate;
    }

    set autoRotate(v)
    {
        this._controls.autoRotate = v;
    }

    get damping()
    {
        return this._controls['damping'];
    }

    set damping(v)
    {
        this._controls['damping'] = v;
    }

    init()
    {
        super.init();

        this._controls = new OrbitControls(this.camera.entity as any, this.domElement);
        watcher.watch(this as OrbitControls3D, 'enabled', this._enabledChanged, this);

        this._controls.addEventListener('change', this._onChange);
    }

    destroy(): void
    {
        watcher.unwatch(this as OrbitControls3D, 'enabled', this._enabledChanged, this);

        this._controls.removeEventListener('change', this._onChange);

        this._controls = null;

        super.destroy();
    }

    update()
    {
        return this._controls.update();
    }

    private _enabledChanged()
    {
        this._controls.enabled = this.enabled;
    }

    private _onChange = () =>
    {
        this.emitter.emit('change');
    };
}
